#include "littlevgl2rtt.h"
#include "lvgl.h"
#include "lv_conf.h"

#include "drv_lcd.h"
#include "drv_touch.h"

static int _lv_init = 0;
static lv_disp_drv_t disp_drv;
static lv_disp_buf_t disp_buf;


static void lcd_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
    /*Return if the area is out the screen*/
    lv_coord_t hres = disp_drv->rotated == 0 ? disp_drv->hor_res : disp_drv->ver_res;
    lv_coord_t vres = disp_drv->rotated == 0 ? disp_drv->ver_res : disp_drv->hor_res;
    /*Return if the area is out the screen*/
    if (area->x2 < 0 || area->y2 < 0 || area->x1 > hres - 1 || area->y1 > vres - 1)
    {
        lv_disp_flush_ready(disp_drv);
        return;
    }
	board_lcd_flush(area->x1,area->y1,(area->x2 - area->x1)+1,(area->y2 - area->y1)+1,(void *)color_p);

    lv_disp_flush_ready(disp_drv);
}

static struct touch_message touch_msg = {0};

static bool input_touch_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
	touch_msg.event = 0;
	board_touch_read_status(&touch_msg);
	data->point.x = touch_msg.x_coordinate;
	data->point.y = touch_msg.y_coordinate;
	if( (touch_msg.event == TOUCH_EVENT_DOWN) || (touch_msg.event == TOUCH_EVENT_MOVE) )
	{
        data->state = LV_INDEV_STATE_PR;
        //rt_kprintf("X:%d Y:%d  %d\n",data->point.x,data->point.y,data->state);
	}else
	{
        data->state = LV_INDEV_STATE_REL;
	}
	return false;
}

extern uint32_t keypad_get_key(void);
static bool input_keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
	static uint32_t last_key = 0;
	uint32_t act_key = 0;//keypad_get_key();
	if(act_key != 0) 
	{
		data->state = LV_INDEV_STATE_PR;
		/*Translate the keys to LVGL control characters according to your key definitions*/
		switch(act_key)
		{
			case 1:
					act_key = '1';
					break;
			case 2:
					act_key = '2';
					break;
			case 3:
					act_key = '3';
					break;
			case 4:
					act_key = '4';
					break;
			case 5:
					act_key = LV_KEY_HOME;
					break;
			case 6:
					act_key = LV_KEY_ESC;
					break;
		}
		last_key = act_key;
  }else 
	{
		data->state = LV_INDEV_STATE_REL;
	}
	data->key = last_key;

	/*Return `false` because we are not buffering and no more data to read*/
  return false;
}

#if LV_USE_LOG
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error", "User"};
void lv_log_print_rtthread(lv_log_level_t level, const char *file,uint32_t line, const char * func, const char * buff)
{
	rt_kputs(lvl_prefix[level]);
	rt_kputs(": ");
	rt_kputs(buff);
	rt_kputs(" \n");
	//rt_kprintf("(#%d %s())\n",line, func);
}
#endif

static lv_color_t  disp_fbuff1[LV_HOR_RES_MAX*LV_VER_RES_MAX];
static lv_color_t  disp_fbuff2[LV_HOR_RES_MAX*LV_VER_RES_MAX];

int lvgl_init(void)
{
    if(_lv_init == 1)
        return 0;

    drv_lcd_init();
    drv_touch_init();
    /* littlevgl Init */
    lv_init();

#if LV_USE_LOG
    /* littlevgl Log Init */
    lv_log_register_print_cb(lv_log_print_rtthread);
#endif

    /* littlevGL Display device interface */
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = LV_HOR_RES_MAX;
    disp_drv.ver_res = LV_VER_RES_MAX;
    disp_drv.flush_cb = lcd_flush;
    lv_disp_buf_init(&disp_buf, disp_fbuff1, disp_fbuff2, LV_HOR_RES_MAX*LV_VER_RES_MAX);
    disp_drv.buffer = &disp_buf;
    lv_disp_drv_register(&disp_drv);
		
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = input_touch_read;
    lv_indev_drv_register(&indev_drv);
		
    static lv_indev_drv_t indev_drv1;
    lv_indev_drv_init(&indev_drv1);
    indev_drv1.type = LV_INDEV_TYPE_KEYPAD;
    indev_drv1.read_cb = input_keypad_read;
    lv_indev_drv_register(&indev_drv1);
		
    _lv_init = 1;
    return RT_EOK;
}


void lvgl_run(void)
{
	uint32_t tick = 10;
	uint32_t rc = 10;
	while (1)
	{
			tick = rt_tick_get();

			rc = lv_task_handler();
//			if(rc<10)
//					rc = 10;
			rt_thread_mdelay(rc);

			tick = rt_tick_get() - tick;
			lv_tick_inc(tick);  //update tick
	}
}


void lvgl_deinit(void)
{
    _lv_init = 0;
}







